////////////////////////////////////////////////////////////////////////
// Last svn revision: $Id:  $ 
////////////////////////////////////////////////////////////////////////

#include <math.h>
#include <assert.h>
#include <iostream>
#include "MLC/Complex.hh"
#include "MLC/ComplexOp.hh"
#include "MLC/DefaultComplexOp.hh"
#include "MLCTest/TComplexOp.hh"

namespace drow {
namespace test {

void TComplexOp::TestClass()
{
    MLC::complexOp = new MLC::def::DefaultComplexOp();
    TestConjugate();
    TestAdd();
    TestSubtract();
    TestMultiply();
    TestMagSquared();
    TestMag();
    TestAngle();
}

MLC::Complex TComplexOp::CreateComplex(double re, double im)
{
    MLC::Complex c;
    c.Re = re;
    c.Im = im;
    return c;
}

void TComplexOp::AssertEquals(const MLC::Complex& a, const MLC::Complex& b)
{
    assert( a.Re == b.Re );
    assert( a.Im == b.Im );
}

void TComplexOp::TestConjugate()
{
    MLC::Complex c = CreateComplex(1,0);
    AssertEquals( MLC::Conjugate(c), CreateComplex(1,0) );
    c.Re = 0; c.Im = 1;
    AssertEquals( MLC::Conjugate(c), CreateComplex(0,-1) );
}

void TComplexOp::TestAdd()
{
    AssertEquals( CreateComplex(1,0) + CreateComplex(0,1), CreateComplex(1,1) );
    AssertEquals( CreateComplex(18,-0.2) + CreateComplex(0.001,1), CreateComplex(18.001,0.8) );
    AssertEquals( CreateComplex(0,0) + CreateComplex(0,0), CreateComplex(0,0) );
    AssertEquals( Add( CreateComplex(1,0), CreateComplex(0,1) ), CreateComplex(1,1) );
}

void TComplexOp::TestSubtract()
{
    AssertEquals( CreateComplex(1,0) - CreateComplex(0,1), CreateComplex(1,-1) );
    AssertEquals( CreateComplex(18,-0.2) - CreateComplex(0.001,1), CreateComplex(17.999,-1.2) );
    AssertEquals( CreateComplex(0.001,1) - CreateComplex(0.001,1), CreateComplex(0,0) );
}

void TComplexOp::TestMultiply()
{
    AssertEquals( CreateComplex(1,0)*CreateComplex(0,1), CreateComplex(0,1) );
    AssertEquals( CreateComplex(1,1)*CreateComplex(1,1), CreateComplex(0,2) );
    AssertEquals( CreateComplex(1,1)*CreateComplex(1,-1), CreateComplex(2,0) );
}

void TComplexOp::TestMagSquared()
{
    assert( MagnitudeSquared(CreateComplex(1,0)) == 1 );
    assert( MagnitudeSquared(CreateComplex(3,4)) == 25 );
    assert( MagnitudeSquared(CreateComplex(0,0)) == 0 );
}

void TComplexOp::TestMag()
{
    assert( Magnitude(CreateComplex(1,0)) == 1 );
    assert( Magnitude(CreateComplex(3,4)) == 5 );
    assert( Magnitude(CreateComplex(0,0)) == 0 );
}

void TComplexOp::TestAngle()
{
    const double pi = atan(1.0)*4;
    assert( Angle(CreateComplex(0,0)) == 0 );
    assert( Angle(CreateComplex(1,0)) == 0 );
    //std::cout << Angle(CreateComplex(1,1)) << std::endl;
    //assert( Angle(CreateComplex(1,1)) == pi/4 );
    //assert( Angle(CreateComplex(0,1)) == pi/2 );
    //assert( Angle(CreateComplex(-1,0)) == pi );
    //assert( Angle(CreateComplex(0,-1)) == -pi/2 );
}

} // namespace MLC
} // namespace drow

